package com.lightkits.wms.domain.deliveryorder.service.impl;

import com.lightkits.common.db.entity.BdDeliveryOrderBase;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.wms.domain.deliveryorder.repo.DeliveryOrderDBService;
import com.lightkits.wms.domain.deliveryorder.service.CreateDeliveryOrderDomain;
import com.lightkits.wms.domain.deliveryorder.service.DeliveryExeDomain;
import com.lightkits.wms.domain.deliveryorder.service.SaveDeliveryDomain;
import com.lightkits.wms.domain.saveonhand.repo.BdEventRecordService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventService;
import com.lightkits.wms.domain.saveonhand.service.UseParamsDomain;
import com.lightkits.wms.dto.deliveryorder.SaveDeliveryOrderResponseType;
import com.lightkits.wms.dto.deliveryorder.model.DeliveryExeDTO;
import com.lightkits.wms.dto.deliveryorder.model.DeliveryOrderDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * SaveDeliveryDomainImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/2/25 10:21
 */
@Component
public class SaveDeliveryDomainImpl implements SaveDeliveryDomain {
    private static final Logger LOGGER = LoggerFactory.getLogger(SaveDeliveryDomainImpl.class);
    private final DeliveryOrderDBService deliveryOrderDBService;

    private final BdEventService bdEvents;

    private final BdEventRecordService bdEventRecords;

    private final CreateDeliveryOrderDomain createDeliveryOrderDomain;

    private final DeliveryExeDomain deliveryExeDomain;

    @Autowired
    public SaveDeliveryDomainImpl(DeliveryOrderDBService deliveryOrderDBService, BdEventService bdEvents, BdEventRecordService bdEventRecords, CreateDeliveryOrderDomain createDeliveryOrderDomain, UseParamsDomain useParamsDomain, DeliveryExeDomain deliveryExeDomain) {
        this.deliveryOrderDBService = deliveryOrderDBService;
        this.bdEvents = bdEvents;
        this.bdEventRecords = bdEventRecords;
        this.createDeliveryOrderDomain = createDeliveryOrderDomain;
        this.deliveryExeDomain = deliveryExeDomain;
    }

    /**
     * 发货单的创建
     *
     * @param deliveryOrderBases 发货单参数
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SaveDeliveryOrderResponseType insertValue(DeliveryOrderDTO deliveryOrderBases) {
        SaveDeliveryOrderResponseType responseType = new SaveDeliveryOrderResponseType();
        responseType.setSuccessful(true);
        CheckResult<BdDeliveryOrderBase> result =
                createDeliveryOrderDomain.createDeliveryOrders(deliveryOrderBases);
        if (!result.isSuccessful() || ObjectUtil.isEmpty(result.getData())) {
            throw new LightKitsBizException(responseType.getMessage());
        }
        BdDeliveryOrderBase orderBase = result.getData();
        //insert delivery Order
        boolean createDEliveryFlag = deliveryOrderDBService.insert(result.getData());
        if (!createDEliveryFlag) {
            throw new LightKitsBizException("Save DeliveryOrder error.");
        }

        List<BdEvent> eventBase = new ArrayList<>();
        List<BdEventRecord> eventRecordBase = new ArrayList<>();
        List<Object> events = orderBase.take();
        for (Object object : events) {
            if (object.getClass().equals(BdEvent.class)) {
                BdEvent event = (BdEvent) object;
                eventBase.add(event);
            }
        }
        boolean insertEventFlag = bdEvents.insertBatch(eventBase);
        if (!insertEventFlag) {
            throw new LightKitsBizException("Save events error.");
        }

        //insert eventRecords and onhandJournals
        for (BdEvent event : eventBase) {
            List<Object> records = event.take();
            for (Object object : records) {
                if (object.getClass().equals(BdEventRecord.class)) {
                    BdEventRecord record = (BdEventRecord) object;
                    record.setEventId(event.getId());
                    eventRecordBase.add(record);
                }
            }
        }

        boolean insertRecordsFlag = bdEventRecords.insertBatch(eventRecordBase);
        if (!insertRecordsFlag) {
            throw new LightKitsBizException("Save eventRecords error.");
        }


        if (deliveryOrderBases.getNewStatus().equals("EXE")) {
            if (ObjectUtil.isNullOrEmpty(deliveryOrderBases.getWarehouseId())) {
                responseType.setSuccessful(false);
                responseType.setMessage("Warehouse cannot be empty at execution");
                responseType.setDeliveryNum(orderBase.getDeliveryOrderNum());
                responseType.setDeliveryId(orderBase.getId().toString());
                return responseType;
            }
            //update delivery Order
            DeliveryExeDTO exeDTO = this.convertDeliveryExeParams(deliveryOrderBases, orderBase.getId());
            if (ObjectUtil.isEmpty(eventBase)) {
                throw new LightKitsBizException("convert Exe fail");
            }
            try {
                deliveryExeDomain.insertValue(exeDTO);
            } catch (LightKitsBizException e) {
                e.fill(responseType);
            }

        }
        responseType.setDeliveryId(orderBase.getId().toString());
        responseType.setDeliveryNum(orderBase.getDeliveryOrderNum());
        return responseType;
    }

    /**
     * 转换发货单的参数
     *
     * @param dto        发货单参数
     * @param deliveryId 发货单ID
     * @return
     */
    private DeliveryExeDTO convertDeliveryExeParams(DeliveryOrderDTO dto, Long deliveryId) {
        DeliveryExeDTO params = new DeliveryExeDTO();
        try {
            params.setDeliveryOrderId(deliveryId.toString());
            params.setParentEventId(dto.getParentEventId());
            params.setRemark(dto.getRemark());
            params.setExeQty(dto.getQuantity());
            params.setWorkerId(dto.getWorkerId());
            params.setWarehouseId(dto.getWarehouseId());
        } catch (Exception e) {
            LOGGER.error("convertParams.error", e);
            throw new LightKitsBizException(e);
        }
        return params;

    }

}
